package com.haha.onebot.start;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.haha.onebot.entity.ActionEvent;
import com.haha.onebot.entity.Bot;
import com.haha.onebot.entity.BotMessage;
import com.haha.onebot.entity.OneBotMessage;
import com.haha.onebot.entity.Status;
import com.haha.onebot.enums.ActionType;
import com.haha.onebot.enums.MetaEventTypeEnum;
import com.haha.onebot.enums.PostTypeEnum;
import com.haha.onebot.enums.SubTypeEnum;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

@Log4j2
@Service
public class BotSocketHandler implements WebSocketHandler {

    @Resource
    private Bot bot;

    private WebSocketSession session;

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private ApplicationEventPublisher eventPublisher;

    @Override
    public void afterConnectionEstablished(@NonNull WebSocketSession session) throws Exception {
        //连接建立
        log.info("连接建立");
        this.session = session;
    }

    @Override
    public void handleMessage(@NonNull WebSocketSession session, @NonNull WebSocketMessage<?> message) {

        //接收消息
        Object payload1 = message.getPayload();
        log.info("接收消息:{}", payload1);
        this.session = session;


        try {
            //解析消息
            OneBotMessage oneBotMessage = objectMapper.readValue(payload1.toString(), OneBotMessage.class);

            String postType = oneBotMessage.getPostType();

            if (postType.equals(PostTypeEnum.META_EVENT.getPostType())) {
                String metaEventType = oneBotMessage.getMetaEventType();
                if (metaEventType.equals(MetaEventTypeEnum.LIFECYCLE.getMetaEventType())) {
                    String subType = oneBotMessage.getSubType();
                    if (subType.equals(SubTypeEnum.CONNECT.getSubType())) {
                        log.info("ws连接成功，开启监听");
                        this.bot.setIsLogin(true);
                        this.bot.setSession(this.session);
                    }
                } else if (metaEventType.equals(MetaEventTypeEnum.HEARTBEAT.getMetaEventType())) {
                    //心跳
                    heartbeatAckOperateHandler(oneBotMessage);
                }
            }

            // 普通消息监听
            if (postType.equals(PostTypeEnum.MESSAGE.getPostType()) || oneBotMessage.getEcho() != null) {
                dispatchOperateHandler(oneBotMessage, "message");
            }

            // 通知消息监听
            if (postType.equals(PostTypeEnum.NOTICE.getPostType())) {
                log.info("这是一个通知");
                log.info(oneBotMessage);
                dispatchOperateHandler(oneBotMessage, "notice");
            }

        } catch (Exception e) {
            log.error("消息解析失败：{}", e);
        }

    }

    private void heartbeatAckOperateHandler(OneBotMessage oneBotMessage) {
        log.info("收到心跳回复");
        Object status = oneBotMessage.getStatus();
        if (!(status instanceof String)) {
            try {
                Status status1 = objectMapper.readValue(objectMapper.writeValueAsString(status), Status.class);
                this.bot.setIsLogin(status1.getGood() && status1.getOnline());
            } catch (JsonProcessingException e) {
                log.error("心跳回复解析失败", e);
            }
        }

    }

    @Override
    public void handleTransportError(@NonNull WebSocketSession session, @NonNull Throwable exception) throws Exception {
        //异常处理
        log.info("异常处理");
        this.bot.setIsLogin(false);
        eventPublisher.publishEvent(ActionEvent.builder()
                .actionType(ActionType.RECONNECTION)
                .build());
    }

    @Override
    public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus closeStatus) throws Exception {
        //连接关闭
        log.info("服务端通知客户端重连");
        this.bot.setIsLogin(false);
        eventPublisher.publishEvent(ActionEvent.builder()
                .actionType(ActionType.RECONNECTION)
                .build());
    }

    /**
     * 事件调度
     *
     * @param oneBotMessage
     */
    private void dispatchOperateHandler(OneBotMessage oneBotMessage, String id) {
        BotMessage botMessage = new BotMessage(this, oneBotMessage, id);
        eventPublisher.publishEvent(botMessage);
    }

    @Override
    public boolean supportsPartialMessages() {
        //是否支持接收不完整的消息
        return false;
    }

}
